package com.zxd.threads.thread_safe;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ClassName:Account
 * Package:com.zxd.threads.thread_safe
 *
 * @Date:2023/9/26 14:25
 * @Author:zxde
 */
public class Account {
    private int balance;

    //使用lock锁的方式做到线程安全
    private final Lock lock = new ReentrantLock();

    public Account(int balance) {
        this.balance = balance;
    }


    public int getBalance() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }

    public void drawMoney(int i) throws InterruptedException {
        //synchronized 同步代码块，传入一个对象，共享此对象的所有线程，都需要获取锁再执行
        //这里建议传入的对象是共享资源的对象，如共享账户，就传入操作的账户对象，this
        synchronized (this) {
            if (this.getBalance() >= i) {
                Thread.sleep(50);
                this.setBalance(this.getBalance() - i);
                System.out.println(Thread.currentThread().getName() + "取钱成功" + "余额 " + this.getBalance());
            } else {
                System.out.println(Thread.currentThread().getName() + "取钱未成功");
            }
        }
    }

    //在方法签名处加上synchronized关键字，将此方法变为同步方法
    public synchronized void drawMoneyMethod(int i) throws InterruptedException {
            if (this.getBalance() >= i) {
                Thread.sleep(50);
                this.setBalance(this.getBalance() - i);
                System.out.println(Thread.currentThread().getName() + "取钱成功" + "余额 " + this.getBalance());
            } else {
                System.out.println(Thread.currentThread().getName() + "取钱未成功");
            }
    }

    public  void drawMoneyLock(int i)  {
        try {
            //加锁
            lock.lock();
            if (this.getBalance() >= i) {
                Thread.sleep(50);
                this.setBalance(this.getBalance() - i);
                System.out.println(Thread.currentThread().getName() + "取钱成功" + "余额 " + this.getBalance());
            } else {
                System.out.println(Thread.currentThread().getName() + "取钱未成功");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //解锁
            lock.unlock();
        }
    }

    public static void testMethod(){
        //静态方法内部加锁，对象使用类名.class
        synchronized (Account.class){
            System.out.println("静态方法加锁");
        }
    }
}
